package com.winning.ds.common.service.impl;


import com.google.common.base.CharMatcher;
import com.google.common.collect.Maps;
import com.google.common.collect.Range;
import com.google.common.collect.TreeRangeMap;
import com.winning.ds.common.config.multiDatasource.DataSource;
import com.winning.ds.common.dao.PtZlfxDao;
import com.winning.ds.common.service.PtZlfxService;
import com.winning.ds.common.util.DateUtil;
import com.winning.ds.common.util.HtmlGenerator;
import com.winning.ds.common.util.PdfGenerator;
import com.winning.ds.common.util.Tuples;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.javatuples.Pair;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

/**
 * @作者：SUNQ
 * @时间：2020/10/13
 */
@Service
@Slf4j
public class PtZlfxServiceImpl implements PtZlfxService {

    @Resource
    private PtZlfxDao ptZlfxDao;


    @Override
    @DataSource(DataSource.index)
    public List<Map> queryDrpfData (Map<String,Object> queryParams) {

        // 当前查询日期（yyyy-MM-dd）
        String beginDate = (String)queryParams.get("beginDate");
        String endDate = (String)queryParams.get("endDate");

        // 查询日期前一天
        final String FORMATER = "yyyy-MM-dd";
        String beginDateAfter1Day = DateUtil.getDateAfterDays(beginDate, FORMATER, -1);
        String endDateAfter1Day = DateUtil.getDateAfterDays(endDate, FORMATER, -1);

        BigDecimal bcdf=new BigDecimal("0");
        BigDecimal scdf=new BigDecimal("0");
        BigDecimal dfbh=new BigDecimal("0");

        //获取上阶段查询时间
        Pair<String, String> beforePch = buildPchFromQueryDate(beginDateAfter1Day, endDateAfter1Day);
        queryParams.put("beginDate", beforePch.getValue0());
        queryParams.put("endDate", beforePch.getValue1());
        //查询上一阶段得分
        List<Map> queryList=ptZlfxDao.queryDrpfData(queryParams);
        if(queryList!=null && queryList.size()>0 && queryList.get(0)!=null){
             scdf =(BigDecimal)(queryList.get(0).get("bcdf")); //上阶段得分
        }

        Pair<String, String> currentPch = buildPchFromQueryDate(beginDate, endDate);
        queryParams.put("beginDate", currentPch.getValue0());
        queryParams.put("endDate", currentPch.getValue1());

        queryList=ptZlfxDao.queryDrpfData(queryParams);
        if(queryList!=null && queryList.size()>0 && queryList.get(0)!=null){
            bcdf =(BigDecimal)(queryList.get(0).get("bcdf"));  //本阶段得分
        }

        if(bcdf!=null && scdf!=null){
             dfbh =bcdf.subtract(scdf);  //获取得分变化
        }
        bcdf = bcdf.setScale(2,BigDecimal.ROUND_HALF_UP); //保留两位小数
        dfbh = dfbh.setScale(2,BigDecimal.ROUND_HALF_UP);
        scdf = scdf.setScale(2,BigDecimal.ROUND_HALF_UP);

        Map map = new HashMap();
        map.put("bcdf",bcdf);//本次得分
        map.put("scdf",scdf);//上次得分
        map.put("dfbh",dfbh);//得分变化
        List<Map> result = new ArrayList();
        result.add(map);
        return  result;
    }

    /**
     * 根据查询日期构造批次号
     * @param beginDate 开始日期(yyyy-MM-dd)
     * @param endDate 结束日期(yyyy-MM-dd)
     * @return 批次号（yyyyMMdd-yyyyMMdd）
     */
    private Pair<String, String> buildPchFromQueryDate(String beginDate, String endDate) {

        String digitBeginDate = CharMatcher.digit().retainFrom(beginDate);
        String digitEndDate = CharMatcher.digit().retainFrom(endDate);
        String beginPch = digitBeginDate + "-" + digitBeginDate;
        String endPch = digitEndDate + "-" + digitEndDate;

        return Tuples.of(beginPch, endPch);
    }

    private Map<String,Object> getQueryParams (Map<String,Object> queryParams) {

        Pair<String, String> pair = buildPchFromQueryDate((String) queryParams.get("beginDate"), (String) queryParams.get("endDate"));

        Map<String,Object> queryParamsAfter=new HashMap<>();
        if (StringUtils.length((String)queryParams.get("beginDate")) >10) {
            queryParamsAfter.put("beginDate",queryParams.get("beginDate"));
            queryParamsAfter.put("endDate",queryParams.get("endDate"));
        } else {
            queryParamsAfter.put("beginDate",pair.getValue0());
            queryParamsAfter.put("endDate",pair.getValue1());
        }
        queryParamsAfter.put("jgbm",queryParams.get("jgbm"));
        queryParamsAfter.put("jgbmList",queryParams.get("jgbmList"));
        return queryParamsAfter;
    }

    /**
     * 查询总机构数，如果jgbmList为空，则查询全部结构数，否则为jgbmList中总和
     * @param queryParams
     * @return
     */
    private Integer queryAllJgCount(Map<String,Object> queryParams) {
        Integer count;
        List jgbmList = (List) queryParams.get("jgbmList");
        if (CollectionUtils.isEmpty(jgbmList)) {
            count = ptZlfxDao.queryZjgCount(queryParams);
        } else {
            count = jgbmList.size();
        }
        return count;
    }

    @Override
    @DataSource(DataSource.index)
    public List<Map> queryScjgData(Map<String,Object> queryParams) {
        List<Map> result = new ArrayList();
        Map map = new HashMap();

        queryParams = getQueryParams(queryParams);

        List<Map> scjgResult =  ptZlfxDao.queryScjgData(queryParams);

        Integer zjgCount = queryAllJgCount(queryParams);
        map.put("zjg", zjgCount);
        map.put("scjg",scjgResult.size());
        map.put("wscjg",zjgCount-scjgResult.size());

        result.add(map);
        return result;
    }

    @Override
    @DataSource(DataSource.index)
    public List<Map> queryWscjgData(Map<String, Object> queryParams) {
        queryParams = getQueryParams(queryParams);
        return ptZlfxDao.queryWscjgData(queryParams);
    }

    @Override
    @DataSource(DataSource.index)
    public List<Map> queryHgjgData(Map<String,Object> queryParams) {

        Map map = new HashMap();
        queryParams = getQueryParams(queryParams);

        List<Map> hgjgResult =  ptZlfxDao.queryHgjgData(queryParams);
        Integer zjgCount = queryAllJgCount(queryParams);
        int hgjg = hgjgResult.size();

        map.put("hgjg",hgjg);
        map.put("whgjg",zjgCount- hgjg);
        map.put("zpfjg",zjgCount);

        List<Map> result = new ArrayList();
        result.add(map);
        return result;
    }

    @Override
    @DataSource(DataSource.index)
    public List<Map> queryWhgjgData(Map<String,Object> queryParams) {
        queryParams = getQueryParams(queryParams);

        List<Map> whgjgResult =   ptZlfxDao.queryWhgjgData(queryParams);
        return whgjgResult;
    }

    @Override
    @DataSource(DataSource.index)
    public List<Map> queryMzgzData(Map<String,Object> queryParams) {

        List<Map> result = new ArrayList();
        Map map = new HashMap();

        queryParams = getQueryParams(queryParams);

        List<Map> hgjgResult =  ptZlfxDao.queryMzgzData(queryParams);

        Object zgzObject=hgjgResult.get(0).get("num");
        Object wmzgzObject=hgjgResult.get(1).get("num");
        //oracle是BigDecimal，SQL server是int，dm是long
        if(zgzObject instanceof Integer && wmzgzObject instanceof Integer){
            int zgz =((Integer) zgzObject).intValue();
            int wmzgz =((Integer) wmzgzObject).intValue() == 0 ? zgz : ((Integer) wmzgzObject).intValue();
            int mzgz = zgz-wmzgz;
            map.put("mzgz",mzgz);
            map.put("wmzgz",wmzgz);
            map.put("zgz",zgz);
        }else if (zgzObject instanceof Long && wmzgzObject instanceof Long){
            int zgz =((Long) zgzObject).intValue();
            int wmzgz =((Long) wmzgzObject).intValue() == 0 ? zgz : ((Long) wmzgzObject).intValue();
            int mzgz = zgz-wmzgz;
            map.put("mzgz",mzgz);
            map.put("wmzgz",wmzgz);
            map.put("zgz",zgz);
        } else {
            BigDecimal zgz =(BigDecimal)zgzObject;
            BigDecimal wmzgz =(BigDecimal)wmzgzObject;
            wmzgz = wmzgz.intValue() == 0 ? zgz : wmzgz;
            BigDecimal mzgz = zgz.subtract(wmzgz);

            map.put("mzgz",mzgz);
            map.put("wmzgz",wmzgz);
            map.put("zgz",zgz);
        }


        result.add(map);
        return result;
    }

    @Override
    @DataSource(DataSource.index)
    public List<Map> queryPfqsData(Map<String,Object> queryParams) {
        queryParams = getQueryParams(queryParams);
        return ptZlfxDao.queryPfqsData(queryParams);
    }

    @Override
    @DataSource(DataSource.index)
    public List<Map> queryCwlqsData(Map<String, Object> queryParams) {
        queryParams = getQueryParams(queryParams);
        return ptZlfxDao.queryCwlqsData(queryParams);
    }

    @Override
    @DataSource(DataSource.index)
    public List<Map> queryPfzsData(Map<String,Object> queryParams) {
        queryParams = getQueryParams(queryParams);
        return ptZlfxDao.queryPfzsData(queryParams);
    }

    @Override
    @DataSource(DataSource.index)
    public List<Map> queryDfpmData(Map<String,Object> queryParams) {
        queryParams = getQueryParams(queryParams);
        return ptZlfxDao.queryDfpmData(queryParams);
    }

    @Override
    @DataSource(DataSource.index)
    public List<Map> queryCwlxData(Map<String,Object> queryParams) {
        queryParams = getQueryParams(queryParams);
        return ptZlfxDao.queryCwlxData(queryParams);
    }

    @Override
    @DataSource(DataSource.index)
    public Map exportReport(Map<String,Object> queryParams) {
        Map resultMap = new HashMap();
        Map<String,Object> queryParams1= getQueryParams(queryParams);

         //获取标题机构名称
        String title=(String) queryParams.get("jgmc");
        resultMap.put("title",title);
        //一.区域总体数据质量情况
        //机构得分
        Map JgdfMap = queryDrpfData(queryParams).get(0);
        String dfbh = getdfChaValue((BigDecimal)JgdfMap.get("bcdf"),(BigDecimal)JgdfMap.get("scdf"));
        resultMap.put("bcdf",JgdfMap.get("bcdf"));
        resultMap.put("dfbh",dfbh);
        //查询机构详情
        Map JgxqMap = ptZlfxDao.queryJgxqData(queryParams1).get(0);
        resultMap.putAll(JgxqMap);
        //二.下级机构数据质量情况
        //合格机构
        Map hgxqMap = queryHgjgData(queryParams).get(0); //用原始参数
        //合格分数
        String hgfs=ptZlfxDao.queryHgfsData();
        //机构排名
        List JgdfList = ptZlfxDao.queryJgdfData(queryParams1);
        resultMap.put("scjgs",JgdfList.size());
        resultMap.put("JgdfList",JgdfList);
        resultMap.putAll(hgxqMap);
        resultMap.put("hgfs",hgfs);
        //三.错误分析
        List cwgzList = ptZlfxDao.queryCwgzData(queryParams1);
        resultMap.put("cwgzList",cwgzList);

        return resultMap;
    }


    public static String getdfChaValue(BigDecimal bcdf,BigDecimal scdf)
    {

        String  dfqkValue = "较昨日<span style=\"color:#82D900;\">无变化</span>";

        int a = bcdf.compareTo(scdf);
        if(a==1)
        {
            BigDecimal result = bcdf.subtract(scdf);
            dfqkValue = "较昨日<span style=\"color:red;\">上升了"+result+"分</span>";
        }else if(a==-1){
            BigDecimal result = scdf.subtract(bcdf);
            dfqkValue = "较昨日<span style=\"color:#82D900;\">下降了"+result+"分</span>";
        }
        return dfqkValue;
    }

    /**
     * 查年运行情况 热力图
     *
     * @return
     */
    @Override
    @DataSource(DataSource.index)
    public Map queryNyxqkRlt(Map<String, Object> queryParams) {
        Map resMap = new HashMap();

        String searchDate = (String) queryParams.get("beginDate");
        int searchYear = Integer.parseInt(searchDate.substring(0, 4));

        final List<String> weeks = Arrays.asList("第四周", "第三周", "第二周", "第一周");
        final List<String> months = Arrays.asList("01月", "02月", "03月", "04月", "05月", "06月", "07月", "08月", "09月", "10月", "11月", "12月");

        Map<String, Object> params = Maps.newHashMap();
        params.put("year", searchYear);
        params.put("jgbmList", queryParams.get("jgbmList"));
        params.put("jgbm", queryParams.get("jgbm"));

        List<Map> lists = ptZlfxDao.queryDayPjdfData(params);

        TreeRangeMap<String, BigDecimal> sourceRangeMap = TreeRangeMap.create();
        lists.forEach(s -> sourceRangeMap.put(Range.singleton((String) s.get("pfkssj")), (BigDecimal) s.get("bcdf")));

        List returnData = new ArrayList();

        LocalDate now = LocalDate.now();
        int currentMonth = now.getMonthValue();
        for (int month = 1; month <= months.size(); month++) {
            if (now.getYear() == searchYear && month > currentMonth) {
                continue;
            }
            for (int week = 1; week <= weeks.size(); week++) {
                String beginDate = DateUtil.getMondayOfMonth(searchYear, month, week);   // 获取第n个周一
                String endDate = DateUtil.getDateAfterDays(beginDate, "yyyy-MM-dd", 6);//获取第n个周七
                String today = cn.hutool.core.date.DateUtil.today(); // yyyy-MM-dd
                // 结束日期不能大于当前日期
                Date date1 = cn.hutool.core.date.DateUtil.parse(today).toJdkDate();
                Date date2 = cn.hutool.core.date.DateUtil.parse(endDate).toJdkDate();
                if (cn.hutool.core.date.DateUtil.compare(date2, date1) > 0) {
                    endDate = today;
                }

                if (LocalDate.now().isBefore(LocalDate.parse(beginDate))) {
                    continue;
                }
                double avg = calcAvg(sourceRangeMap, beginDate, endDate);

                Object[] xyz = new Object[] {month - 1, 4 - week, avg};
                if (avg > 0) {
                    returnData.add(xyz);
                }

            }
        }

        resMap.put("x", months);  // x轴系列
        resMap.put("y", weeks);  // y轴系列
        resMap.put("data", returnData);    // 坐标及数据
        return resMap;
    }

    /**
     * 计算周热力分布图平均值
     * @author xmliu
     * @param sources 日数据，day为key，当前得分作为value
     * @param startDay 当前月份的第N周的开始日期
     * @param endDay 当前月份的第N周的结束日期
     * @return 区间内当前得分的平均值
     */
    private double calcAvg(TreeRangeMap<String, BigDecimal> sources, String startDay, String endDay) {

        Map<Range<String>, BigDecimal> rangeMap = sources.subRangeMap(Range.closed(startDay, endDay)).asMapOfRanges();
        double avg = rangeMap.values().stream().mapToDouble(BigDecimal::doubleValue).average().orElse(0D);

        // 保留两位小数
        double scaleAvg = BigDecimal.valueOf(avg).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        return scaleAvg;
    }

    /**
     * 采集完整度和评分分布
     * @param queryParams
     * @return
     */
    @Override
    @DataSource(DataSource.index)
    public List<Map> queryCjwzdPffbData(Map<String, Object> queryParams) {

        String yyyyMMdd = CharMatcher.digit().retainFrom((String) queryParams.get("beginDate"));
        String pch = yyyyMMdd + "-" + yyyyMMdd;
        queryParams.put("pch", pch);
        return ptZlfxDao.queryCjwzdPffbData(queryParams);

    }

    @Override
    @DataSource(DataSource.index)
    public List<Map> queryJgjzzlData(Map<String, Object> queryParams) {
        String yyyyMMdd = CharMatcher.digit().retainFrom((String) queryParams.get("beginDate"));
        String pch = yyyyMMdd + "-" + yyyyMMdd;
        queryParams.put("pch", pch);
        return ptZlfxDao.queryJgjzzlData(queryParams);
    }

    @Override
    @DataSource(DataSource.index)
    public String getReportPath(Map<String, Object> queryParams) {
        String filePath = "";
        String searchDate = (String) queryParams.get("beginDate");
        //获取时间并转换格式
        String jgbmValue = (String) queryParams.get("jgbm");
        String jgmcValue = (String) queryParams.get("jgmc");
        //查询数据
        Map resultMap = this.exportReport(queryParams);

        Map<String, Object> variables = new HashMap<String, Object>();

        variables.put("title", "质控报告");
        variables.put("searchDate", searchDate);
        variables.put("resultMap", resultMap);
        try {
            //服务端的绝对目录，项目根目录
            filePath = System.getProperty("catalina.home");
            //文件夹路径
            String direPath = filePath + "/reportFiles/";
            File direFile = new File(direPath);
            //没有则创建文件夹
            if (!direFile.exists()) {
                try {
                    direFile.mkdirs();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            String htmlStr = HtmlGenerator.generate("dqmt-ptTemplate.html", variables);
            filePath = direPath + searchDate + "-" + jgbmValue + "-" + "zkbg-day.pdf";
            OutputStream out = new FileOutputStream(URLDecoder.decode(filePath, "UTF-8"));

            PdfGenerator pdfgenerator = new PdfGenerator();
            //生成文档
            pdfgenerator.generatePlus(htmlStr, out);
        } catch (Exception e) {
            log.error("质控报告生成异常:", e);
        }
        return filePath;
    }
}
